module SoftRenderer {
    export class Face {
        constructor (public a:number, public b:number, public c:number) {}
    }

    export class Mesh {
    	public position:BABYLON.Vector3;
    	public rotation:BABYLON.Vector3;
    	public scale:BABYLON.Vector3;

    	public vertices:BABYLON.Vector3[];
        public colors:BABYLON.Color4[];
        public faces:Face[];

    	constructor (verticesCount:number = 0, facesCount:number = 0) {
    		this.position = BABYLON.Vector3.Zero();
    		this.rotation = BABYLON.Vector3.Zero();
    		this.scale = new BABYLON.Vector3(1, 1, 1);
    		this.vertices = new Array(verticesCount);
            this.colors = new Array(verticesCount);
            this.faces = new Array(facesCount);
    	}

    	public static Box (color:BABYLON.Color4) :Mesh {
    		var mesh = new Mesh();

            var colorCopy = color.clone();

    		mesh.vertices.push(new BABYLON.Vector3(-1, 1, 1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(1, 1, 1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(-1, -1, 1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(1, -1, 1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(-1, 1, -1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(1, 1, -1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(1, -1, -1));
            mesh.colors.push(colorCopy);

			mesh.vertices.push(new BABYLON.Vector3(-1, -1, -1));
            mesh.colors.push(colorCopy);

            mesh.faces.push(new Face(0, 1, 2));
            mesh.faces.push(new Face(1, 2, 3));
            mesh.faces.push(new Face(1, 3, 6));
            mesh.faces.push(new Face(1, 5, 6));
            mesh.faces.push(new Face(0, 1, 4));
            mesh.faces.push(new Face(1, 4, 5));
            mesh.faces.push(new Face(2, 3, 7));
            mesh.faces.push(new Face(3, 6, 7));
            mesh.faces.push(new Face(0, 2, 7));
            mesh.faces.push(new Face(0, 4, 7));
            mesh.faces.push(new Face(4, 5, 6));
            mesh.faces.push(new Face(4, 6, 7));

			return mesh;
    	}

        public static createMeshesFromJson (jsonObject) :Mesh[] {
            var subMeshes:Mesh[] = [];
            for (var meshIndex = 0; meshIndex < jsonObject.meshes.length; meshIndex++) {
                var verticesArray:number[] = jsonObject.meshes[meshIndex].vertices;
                var indicesArray: number[] = jsonObject.meshes[meshIndex].indices;
                var uvCount:number = jsonObject.meshes[meshIndex].uvCount;

                // Depending of the number of texture's coordinates per vertex
                // we're jumping in the vertices array  by 6, 8 & 10 windows frame
                var verticesStep = 1;
                switch (uvCount) {
                    case 0:
                       verticesStep = 6;
                       break;
                    case 1:
                       verticesStep = 8;
                       break;
                    case 2:
                       verticesStep = 10;
                       break;
                }

                // the number of interesting vertices information for us
                var verticesCount = verticesArray.length / verticesStep;
                // number of faces is logically the size of the array divided by 3 (A, B, C)
                var facesCount = indicesArray.length / 3;
                
                var subMesh = new Mesh(verticesCount, facesCount);
                       
                // Filling the Vertices array of our mesh first
                var colorDefault = BABYLON.Color3.White().toColor4();
                for (var index = 0; index < verticesCount; index++) {
                    var x = verticesArray[index * verticesStep];
                    var y = verticesArray[index * verticesStep + 1];
                    var z = verticesArray[index * verticesStep + 2];
                    subMesh.vertices[index] = new BABYLON.Vector3(x, y, z);
                    subMesh.colors[index] = colorDefault;
                }
                       
                // Then filling the Faces array
                for (var index = 0; index < facesCount; index++) {
                    var a = indicesArray[index * 3];
                    var b = indicesArray[index * 3 + 1];
                    var c = indicesArray[index * 3 + 2];
                    subMesh.faces[index] = new Face(a, b, c);
                }
                
                // Getting the position you've set in Blender
                var position = jsonObject.meshes[meshIndex].position;
                subMesh.position = new BABYLON.Vector3(position[0], position[1], position[2]);

                subMeshes.push(subMesh);
            }
            return subMeshes;
        }
    }
}
